package com.pactera.asmp.server.utils;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
//import sun.misc.BASE64Decoder;
//import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


public class RSAUtil {

	/**
	 * 加解密算法类型
	 */
	private static final String KEY_ALGORITHM = "RSA";

	/**
	 * 签名算法
	 */
	private static final String SIGNATURE_ALGORITHM = "SHA256WithRSA";
	/**
	 * rsa加密算法描述
	 */
	private static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";// "RSA/ECB/PKCS1Padding"

	private static final int KEY_BIT = 1024;

	private static ConcurrentHashMap<String, RSAPrivateKey> rsaPriKeyMap = new ConcurrentHashMap<String, RSAPrivateKey>();

	private static ConcurrentHashMap<String, RSAPublicKey> rsaPubKeyMap = new ConcurrentHashMap<String, RSAPublicKey>();

	/**
	 * RAS加密
	 *
	 * @param publicKeyStr 公钥
	 * @param plainBytes 待加密信息
	 * @return byte[]
	 * @throws Exception
	 */
	public static byte[] encryptRSA(byte[] plainBytes, boolean useBase64Code, String charset, String publicKeyStr)
			throws Exception {
		PublicKey publicKey = getPublicKey(publicKeyStr);
		// String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding"; // 加密block需要预留11字节
		int keybit = KEY_BIT;
		int reservebytes = 11;
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		int decryptBlock = keybit / 8; // 256 bytes
		int encryptBlock = decryptBlock - reservebytes; // 245 bytes
		// 计算分段加密的block数 (向上取整)
		int nBlock = (plainBytes.length / encryptBlock);
		if ((plainBytes.length % encryptBlock) != 0) { // 余数非0，block数再加1
			nBlock += 1;
		}
		// 输出buffer, 大小为nBlock个decryptBlock
		ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * decryptBlock);
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		// cryptedBase64Str =
		// Base64.encodeBase64String(cipher.doFinal(plaintext.getBytes()));
		// 分段加密
		for (int offset = 0; offset < plainBytes.length; offset += encryptBlock) {
			// block大小: encryptBlock 或 剩余字节数
			int inputLen = (plainBytes.length - offset);
			if (inputLen > encryptBlock) {
				inputLen = encryptBlock;
			}
			// 得到分段加密结果
			byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
			// 追加结果到输出buffer中
			outbuf.write(encryptedBlock);
		}
		// 如果是Base64编码，则返回Base64编码后的数组
		if (useBase64Code) {
			return Base64.encode(outbuf.toByteArray()).getBytes(charset);
		} else {
			return outbuf.toByteArray(); // ciphertext
		}
	}

	/**
	 * RAS加密
	 *
	 * @param privateKeyStr 私钥
	 * @param plainBytes 待加密信息
	 * @return byte[]
	 * @throws Exception
	 */
	public static byte[] encryptRSAByPri(byte[] plainBytes, boolean useBase64Code, String charset, String privateKeyStr)
			throws Exception {
		PrivateKey privateKey = getPrivateKey(privateKeyStr);
		// String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding"; // 加密block需要预留11字节
		int keybit = KEY_BIT;
		int reservebytes = 11;
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		int decryptBlock = keybit / 8; // 256 bytes
		int encryptBlock = decryptBlock - reservebytes; // 245 bytes
		// 计算分段加密的block数 (向上取整)
		int nBlock = (plainBytes.length / encryptBlock);
		if ((plainBytes.length % encryptBlock) != 0) { // 余数非0，block数再加1
			nBlock += 1;
		}
		// 输出buffer, 大小为nBlock个decryptBlock
		ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * decryptBlock);
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		// cryptedBase64Str =
		// Base64.encodeBase64String(cipher.doFinal(plaintext.getBytes()));
		// 分段加密
		for (int offset = 0; offset < plainBytes.length; offset += encryptBlock) {
			// block大小: encryptBlock 或 剩余字节数
			int inputLen = (plainBytes.length - offset);
			if (inputLen > encryptBlock) {
				inputLen = encryptBlock;
			}
			// 得到分段加密结果
			byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
			// 追加结果到输出buffer中
			outbuf.write(encryptedBlock);
		}
		// 如果是Base64编码，则返回Base64编码后的数组
		if (useBase64Code) {
			return Base64.encode(outbuf.toByteArray()).getBytes(charset);
		} else {
			return outbuf.toByteArray(); // ciphertext
		}
	}

	/**
	 * RSA解密
	 *
	 * @param rsaPrivateKeyStr 私钥
	 * @param cryptedBytes 待解密信息
	 * @return byte[]
	 * @throws Exception
	 */
	public static byte[] decryptRSA(byte[] cryptedBytes, boolean useBase64Code, String charset, String rsaPrivateKeyStr)
			throws Exception {
		RSAPrivateKey rsAPrivateKey = getPrivateKey(rsaPrivateKeyStr);
		String cipher_algorithm = CIPHER_ALGORITHM; // 加密block需要预留11字节
		byte[] data = null;
		// 如果是Base64编码的话，则要Base64解码
		if (useBase64Code) {
			data = Base64.decode(new String(cryptedBytes, charset));
		} else {
			data = cryptedBytes;
		}

		int keybit = KEY_BIT;
		int reservebytes = 11;
		Cipher cipher = Cipher.getInstance(cipher_algorithm);
		int decryptBlock = keybit / 8; // 256 bytes
		int encryptBlock = decryptBlock - reservebytes; // 245 bytes
		// 计算分段解密的block数 (理论上应该能整除)
		int nBlock = (data.length / decryptBlock);
		// 输出buffer, , 大小为nBlock个encryptBlock
		ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * encryptBlock);
		cipher.init(Cipher.DECRYPT_MODE, rsAPrivateKey);
		// plaintext = new
		// String(cipher.doFinal(Base64.decodeBase64(cryptedBase64Str)));
		// 分段解密
		for (int offset = 0; offset < data.length; offset += decryptBlock) {
			// block大小: decryptBlock 或 剩余字节数
			int inputLen = (data.length - offset);
			if (inputLen > decryptBlock) {
				inputLen = decryptBlock;
			}

			// 得到分段解密结果
			byte[] decryptedBlock = cipher.doFinal(data, offset, inputLen);
			// 追加结果到输出buffer中
			outbuf.write(decryptedBlock);
		}
		outbuf.flush();
		outbuf.close();
		return outbuf.toByteArray();
	}

	/**
	 * RSA解密
	 *
	 * @param publicKeyStr 公钥
	 * @param cryptedBytes 待解密信息
	 * @return byte[]
	 * @throws Exception
	 */
	public static byte[] decryptRSAByPub(byte[] cryptedBytes, boolean useBase64Code, String charset, String publicKeyStr)
			throws Exception {
		PublicKey publicKey = getPublicKey(publicKeyStr);
		String cipher_algorithm = CIPHER_ALGORITHM; // 加密block需要预留11字节
		byte[] data = null;
		// 如果是Base64编码的话，则要Base64解码
		if (useBase64Code) {
			data = Base64.decode(new String(cryptedBytes, charset));
		} else {
			data = cryptedBytes;
		}

		int keybit = KEY_BIT;
		int reservebytes = 11;
		Cipher cipher = Cipher.getInstance(cipher_algorithm);
		int decryptBlock = keybit / 8; // 256 bytes
		int encryptBlock = decryptBlock - reservebytes; // 245 bytes
		// 计算分段解密的block数 (理论上应该能整除)
		int nBlock = (data.length / decryptBlock);
		// 输出buffer, , 大小为nBlock个encryptBlock
		ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * encryptBlock);
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		// plaintext = new
		// String(cipher.doFinal(Base64.decodeBase64(cryptedBase64Str)));
		// 分段解密
		for (int offset = 0; offset < data.length; offset += decryptBlock) {
			// block大小: decryptBlock 或 剩余字节数
			int inputLen = (data.length - offset);
			if (inputLen > decryptBlock) {
				inputLen = decryptBlock;
			}

			// 得到分段解密结果
			byte[] decryptedBlock = cipher.doFinal(data, offset, inputLen);
			// 追加结果到输出buffer中
			outbuf.write(decryptedBlock);
		}
		outbuf.flush();
		outbuf.close();
		return outbuf.toByteArray();
	}

	/**
	 * <p>
	 * 用私钥对信息生成数字签名
	 * </p>
	 *
	 * @param data 已加密数据
	 * @param privateKey 私钥(BASE64编码)
	 * @return
	 * @throws Exception
	 */
	public static String generateSign(byte[] data, String privateKey) throws Exception {
		byte[] keyBytes = Base64.decode(privateKey);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(privateK);
		signature.update(data);
		return Base64.encode(signature.sign());
	}

	/**
	 * <p>
	 * 校验数字签名
	 * </p>
	 *
	 * @param data 已加密数据
	 * @param publicKey 公钥(BASE64编码)
	 * @param sign 数字签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verifySign(byte[] data, String publicKey, String sign) throws Exception {
		byte[] keyBytes = Base64.decode(publicKey);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		PublicKey publicK = keyFactory.generatePublic(keySpec);
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(publicK);
		signature.update(data);
		return signature.verify(Base64.decode(sign));
	}

	/**
	 * 从字符串中加载公钥
	 *
	 * @param publicKeyStr 公钥数据字符串
	 * @throws Exception 加载公钥时产生的异常
	 */
	private static RSAPublicKey getPublicKey(String publicKeyStr) throws Exception {
		RSAPublicKey publicKey = rsaPubKeyMap.get(publicKeyStr);
		if (publicKey != null) {
			return publicKey;
		}
		try {
//			BASE64Decoder base64Decoder = new BASE64Decoder();
			byte[] buffer = Base64.decode(publicKeyStr);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
			publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
			rsaPubKeyMap.put(publicKeyStr, publicKey);
			return publicKey;
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("公钥非法");
//		} catch (IOException e) {
//			throw new Exception("公钥数据内容读取错误");
		} catch (NullPointerException e) {
			throw new Exception("公钥数据为空");
		}
	}

	private static RSAPrivateKey getPrivateKey(String privateKeyStr) throws Exception {
		RSAPrivateKey privateKey = rsaPriKeyMap.get(privateKeyStr);
		if (privateKey != null) {
			return privateKey;
		}
		try {
			//BASE64Decoder base64Decoder = new BASE64Decoder();
			byte[] buffer = Base64.decode(privateKeyStr);
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
			rsaPriKeyMap.put(privateKeyStr, privateKey);
			return privateKey;
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("私钥非法");
//		} catch (IOException e) {
//			throw new Exception("私钥数据内容读取错误");
		} catch (NullPointerException e) {
			throw new Exception("私钥数据为空");
		}
	}

	private static  final String PUBLIC_KEY = "PUBLIC_KEY";

	private static  final String PRIVATE_KEY = "PRIVATE_KEY";
	
	public static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
	
	//获得公钥字符串
    public static String getPublicKeyStr(Map<String, Object> keyMap) throws Exception {
        //获得map中的公钥对象 转为key对象
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        //编码返回字符串
        return encryptBASE64(key.getEncoded());
    }
 
    //获得私钥字符串
    public static String getPrivateKeyStr(Map<String, Object> keyMap) throws Exception {
        //获得map中的私钥对象 转为key对象
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        //编码返回字符串
        return encryptBASE64(key.getEncoded());
    }

	//解码返回byte
    public static byte[] decryptBASE64(String key) throws Exception {
        return Base64.decode(key);
    }
 
    //编码返回字符串
    public static String encryptBASE64(byte[] key) throws Exception {
        return Base64.encode(key);
    }


	private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

	/**
     * 将byte[]转换为16进制字符串
     */
    public static String bytesToHex(byte[] bytes) {
        //一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 2];
        int a = 0;
        int index = 0;
        for(byte b : bytes) { // 使用除与取余进行转换
            if(b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }
 
            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
        }
        return new String(buf);
    }
    /**
     * 将16进制字符串转换为byte[]
     *
     * @param str
     * @return
     */
    public static byte[] hexToBytes(String str) {
        if(str == null || str.trim().equals("")) {
            return new byte[0];
        }
 
        byte[] bytes = new byte[str.length() / 2];
        for(int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }
 
        return bytes;
    }



	public static void main(String[] args) {
		String content = "0123456789abcdefghijklmnopqrst";
		String rasPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDd6W50lRoyGyYqOzro50db5jmIkItcLDPZj9kYAwjeirBG/62ph5eRRTJOqdyVvRM+HnqHQD3ay7w5Rp/cc28VDatZANPxSBlgdo+Xj05yvDWRxp/R+XMNnGiKBXG9ozmXw7u4DdY/ILKbxEs5pZ8foI5rUXScO4i0xOmuHPAHCPvTiTIB0NiT51D5NFFAfnbe4oGAx7TCH6GhhLfP94GtCLXkiGN5Hg1W83CkZG8gpBt6u8e1Jka2S6ExrdFqW99EYmARpBIn0HOlGAQJu75tQOSg2f/O/jm38c9hmw5IpFlzYVXBTjlDHLGFl0YlG5s4xisgxxIfphIIrAPOTeWjAgMBAAECggEAQwNuPriUK5N1SAWQ+ap2KzNwJmR4IUKb+dRt28l20TWSnC4z9GElDVKXKZg0K+foOrcbi2KEC2HBGo7QUdNuNS5mkz8jwdZjC3ViUYOOTim2B6qysscgznhwPVX9jiYPi1wpgSB0laW7Kjzx9pukXPmwaIo1q8RyuRxJ8TF97rFg3JIfir3GIRePde3uVjgTjBvhaM1RXeAupDBysOYainWL/L5Va9rd+3KQeM3gyntWlwnDBWawIMulhFnMpM3vPGsoJG6nPSkqbssMjQhvhUiReY63J0313A59MwkJL+tXGfw659+BkWiboD4wmFJg2fU84XN5rMH3kz0H0hPBAQKBgQDwtyKWz21aJ3689joiuvme3pBk+FLuB8W5B4UQxhWkli2Lrnu2FfwyGxTcvQt5xo7XzQlsFvKUz+JdgExjOHaBwCJyfQB2EeWXVbIp2UQ4grzyGQxvvgfWO659WQkWB1ab+RsPzFdxDzU7YbAx2ZnAvd+JapH8mq+ZDs5snrY/gQKBgQDsAKRiFvzky04RHUGodaESQkWLcXygMQmJIpsYlD1Sknn214CPtiV+RxPBWma9VoLjl1cWJ2wIn8Zus87tP9HVKZGvG+rzkY87qzSaiMaGI71OGNEVuaK4x5sYX+fKr2ALC6/7HNZ6KnwtPVKZOR0gAJWyykqEGWK1tDpL0v63IwKBgQC5uyR2JrBiWo0Ash/jQk9ulJ3nOm+Kd/bIsJOsgJqcdr/HwiZ0NXx1EM5FD5x2Jo161xqJCx+7ULeBm4fVGvDdZmlt2yNq9p4m6ZlhjuGDlOTDDC67XW3gkAYvc25+T8U07b1CsFFby/cvzU1M+XAX9qku90qTFKuetnzx9Hf8gQKBgHLicSMq65r4+RzNsCuwb2NzDWWvLirRFEJErVmOuDddBLBMAdJzqdbKBOzn9AGRfpAKGSO4txePp8o2D7JgkeYBoWCr53kAT8iNNENR98pO1ZWR8R5xSqxGxtJbxXteWhOmcdl9FU9NJTvkkTPzoKD2h+kMHrAlp26quII2yTYfAoGBAOoyGQ+0KnLVS/ykZvTuBOKhdLbtTnf/JPWWoDCvNKUOdodXQrfNtq693qseIi2DquCLuM86Nj8sgJiM80nCEA1ojOfLz8/3Dp3GWcjEpHgGLaIbLOxDJisu83cYMTb0u0gQL6qjIs43bilSMB9rM00WdIbCKjMihIlSGQYy5fpB";

		String rsaPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3eludJUaMhsmKjs66OdHW+Y5iJCLXCwz2Y/ZGAMI3oqwRv+tqYeXkUUyTqnclb0TPh56h0A92su8OUaf3HNvFQ2rWQDT8UgZYHaPl49Ocrw1kcaf0flzDZxoigVxvaM5l8O7uA3WPyCym8RLOaWfH6COa1F0nDuItMTprhzwBwj704kyAdDYk+dQ+TRRQH523uKBgMe0wh+hoYS3z/eBrQi15IhjeR4NVvNwpGRvIKQbervHtSZGtkuhMa3RalvfRGJgEaQSJ9BzpRgECbu+bUDkoNn/zv45t/HPYZsOSKRZc2FVwU45QxyxhZdGJRubOMYrIMcSH6YSCKwDzk3lowIDAQAB";

		byte[] encryptData;
		try {
			encryptData = RSAUtil.encryptRSA(content.getBytes("UTF-8"), false, "UTF-8", rsaPublicKey);
			// System.out.println(Base64.encodeBase64String(encryptData) + "");
			String encryptDataString = "N5iUC1kddkUjBk7O3DrMLh9C49TuMqjPHZ0lFszSEiU8xfgagosdNjQkSVhfc2bErdVe6IC2LpGtn/j6d9sI11+hZ5vBH4p2VoLxvtV5Zl+DLqHrAJ84h2QKxcaiBVh3zPLA+pYTE7gXyodpl8xa8EfVXhSpVzWYaF6e+oyWFqIodsfQ0XfL6rTEHwgHsSnA2jIonHakouNr0ibfuxWOJNeRD/COQL7PEND9fJOSklrQbmuzjWfJucmUkoKq5FPbvbt6BEsOF21FoMqHh9GZPURuacQaBqGBMVmFM78wc0IDBNpYsBwT50/tE0YiYWItjh3e5chKpK2SeBzpEYU1HA==";
			byte[] desCryptData = RSAUtil.decryptRSA(encryptData, false, "UTF-8", rasPrivateKey);
			// System.out.println(new String(desCryptData));
		} catch (Exception e) {

		}
		// String etcPubKey =
		// "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2mrL01iewpB42zP+tfRJiEeNw8jL0ima9pUIR/RZTYU6vY0prg1RgYUYYdnBt8fUd82tn1HLyzYBNKN/gQTVgCxrKY4Hx15nci0lxpoiBxuIKkZ4YcenRLIjbcr5GwMEPzRXUClNFjFodGFcAiBw6Ls4q7kdl2p38kuekVJJkEwIDAQAB";
		// String md5Str = "e10adc3949ba59abbe56e057f20f883e";
		// String signStr =
		// "94675A84AA2F8F337DB2A06D14B80C81858AE06CC501CF4C522B6701DF1C4C49A50B3B83DBFE5860D8B740D9F6D977FAB63D1C9748034565D26839750990F134F9D0729FAAEA581328E131B305C07C6D7A9352FFB2C05185FAD521141652A2DAA4B9D46CED44E9921B6D0794ECAADCE5E8FA5B1626B6902346802D750A47FF7E";
		//
		// String needDecStr =
		// "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";
		// try {
		// byte[] desCryptData = RSAUtil.decryptRSA(needDecStr.getBytes(), true, "UTF-8", rasPrivateKey);
		// System.out.println(new String(desCryptData) + "");
		// String createSignStr = new String(generateSign(md5Str.getBytes(), rasPrivateKey) + "");
		// System.out.println(createSignStr);
		// } catch (Exception e) {
		//
		// }
	}
}
